package com.shm.singlecamera.Camera;

import android.app.Activity;
import android.content.Context;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.util.Log;
import android.util.SizeF;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

public class CameraStateMachine {

    private static final String TAG = "State Model";

    private static boolean isROI = false;
    public static boolean isROI() {
        return isROI;
    }

    public static void setIsROI(boolean isROI) {
        CameraStateMachine.isROI = isROI;
    }


    public interface CloseStateCallback {
        void onClosed();
    }

    public interface OpenStateCallback {
        void onOpened();
    }

    public interface TextureAdjustStateCallback {
        void onAdjusted();
    }

    public static Set<String> physicsCameras;
    public static String normalCam, wideCam, longCam;
    public static String logicalCam;
    private static boolean isNormal = true;

    public static boolean isNormal() {
        return isNormal;
    }

    public static void setIsNormal(boolean isNormal) {
        CameraStateMachine.isNormal = isNormal;
    }

    public static String getLogicalCam(){
        return logicalCam;
    }

    public static Set<String> getPhysicsCameras() {
        return physicsCameras;
    }

    public static String getNormalCam() {
        return normalCam;
    }

    public static String getWideCam() {
        return wideCam;
    }

    public static String getLongCam() {
        return longCam;
    }

    public static boolean isCamCanWork(){
        return normalCam != null;
    }

    /**
     * 确定相机状态
     * @param activity 传入的上下文环境
     * @return 是否支持双摄
     */
    public static boolean readSupportCam(Activity activity){

        if(physicsCameras != null){
            return physicsCameras.size() == 2;
        }

        //获取管理类
        CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
        assert manager != null;

        //获取所有逻辑ID
        String[] logicalCameraList;
        try {
            logicalCameraList = manager.getCameraIdList();
        } catch (CameraAccessException e) {
            throw new RuntimeException(e);
        }

        //获取逻辑摄像头下拥有多个物理摄像头的类 作为双镜类
        for (String id : logicalCameraList) {
            try {
                CameraCharacteristics cameraCharacteristics = manager.getCameraCharacteristics(id);
                Set<String> physicalLogicalCameras = cameraCharacteristics.getPhysicalCameraIds();
                // 输出支持的逻辑相机id
                if (physicalLogicalCameras.size() >= 2) {
                    // 如果支持双摄，确定主摄和广角
                    String primaryCameraId = null;
                    String wideAngleCameraId = null;
                    String longFocusCameraId = null;

                    // 遍历物理摄像头，确定主摄和广角编号
                    for (String physicalId : physicalLogicalCameras) {
                        CameraCharacteristics characteristics = manager.getCameraCharacteristics(physicalId);

                        // Consider sensor size, aperture, and focal length
                        SizeF sensorSize = characteristics.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);
                        float[] apertures = characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES);
                        float focalLength = Objects.requireNonNull(characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS))[0];

                        // Prioritize larger sensor size and lower f-number for primary camera
                        if (primaryCameraId == null ||
                                (Objects.requireNonNull(sensorSize).getWidth() * sensorSize.getHeight() >
                                        Objects.requireNonNull(manager.getCameraCharacteristics(primaryCameraId).get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE)).getWidth() *
                                                Objects.requireNonNull(manager.getCameraCharacteristics(primaryCameraId).get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE)).getHeight()) &&
                                        (Objects.requireNonNull(apertures)[0] < Objects.requireNonNull(manager.getCameraCharacteristics(primaryCameraId).get(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES))[0])) {
                            primaryCameraId = physicalId;
                        }

                        // Prioritize shorter focal length for wide-angle camera
                        if (wideAngleCameraId == null || focalLength < Objects.requireNonNull(manager.getCameraCharacteristics(wideAngleCameraId).get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS))[0]) {
                            wideAngleCameraId = physicalId;
                        }

                        if (longFocusCameraId == null || focalLength > Objects.requireNonNull(manager.getCameraCharacteristics(wideAngleCameraId).get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS))[0]) {
                            longFocusCameraId = physicalId;
                        }

                    }
                    normalCam = primaryCameraId;
                    wideCam = wideAngleCameraId;
                    longCam = longFocusCameraId;

                    logicalCam = id;
                    physicsCameras = new HashSet<>();
                    physicsCameras.add(normalCam);
                    physicsCameras.add(wideCam);
                    physicsCameras.add(longCam);
                    return true;
                }

            } catch (CameraAccessException e) {
                Log.e(TAG, "error in dual camera: " + e);
            }
        }
        // 如果不支持双摄，取后置摄像头为主摄
        if(normalCam == null){
            for (String id : logicalCameraList) {
                try {
                    CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
                    // 忽略前置摄像头
                    final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
                    if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
                        continue;
                    }

                    final StreamConfigurationMap map =
                            characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

                    if (map == null) {
                        continue;
                    }

                    // 确定了主摄
                    normalCam = id;
                    logicalCam = id;
                    physicsCameras = new HashSet<>();
                    physicsCameras.add(normalCam);

                } catch (CameraAccessException e) {
                    Log.e(TAG, "error in only single camera: " + e);
                }
            }
        }

        return false;
    };

    // 同一个逻辑相机应该保持一致才能正常读取数据
    public static final int CAMERA_TEMPLATE = CameraDevice.TEMPLATE_VIDEO_SNAPSHOT;
    public static final int DUAL_CAMERA_TEMPLATE = CameraDevice.TEMPLATE_VIDEO_SNAPSHOT;

    private static int currentCam = 0;
    private static boolean isRecording = false;
    private static boolean isAELocked = false;

    private static boolean isCamParamChanged = false;

    private static boolean isCamSelected = false;

    private static boolean isAWBLocked = false;

    public static boolean isCamSelected() {
        return isCamSelected;
    }

    public static void setIsCamSelected(boolean isCamSelected) {
        CameraStateMachine.isCamSelected = isCamSelected;
    }

    public static boolean isCamParamChanged() {
        return isCamParamChanged;
    }


    public static void setIsCamParamChanged(boolean isCamParamChanged) {
        CameraStateMachine.isCamParamChanged = isCamParamChanged;
    }

    public static int getCurrentCam() {
        return currentCam;
    }

    public static void setCurrentCam(int currentCam) {
        CameraStateMachine.currentCam = currentCam;
    }

    public static boolean isAELocked() {
        return isAELocked;
    }


    public static boolean isRecording() {
        return isRecording;
    }

    public static void setIsRecording(boolean isRecording) {
        CameraStateMachine.isRecording = isRecording;
    }

    public static void setIsAELocked(boolean isAELocked) {
        CameraStateMachine.isAELocked = isAELocked;
    }

    public static boolean isAWBLocked() {
        return isAWBLocked;
    }

    public static void setIsAWBLocked(boolean isAWBLocked) {
        CameraStateMachine.isAWBLocked = isAWBLocked;
    }

    private static boolean isSurfaceAvailable = false;

    public static void setIsSurfaceAvailable(boolean isSurfaceAvailable) {
        CameraStateMachine.isSurfaceAvailable = isSurfaceAvailable;
    }

    public static boolean isSurfaceAvailable() {
        return isSurfaceAvailable;
    }
}
